#ifndef CLIENT_VISTA_MAINHANDLER_H_
#define CLIENT_VISTA_MAINHANDLER_H_
#include <iostream>
#include <stdio.h>
#include <gtkmm.h>
#include "client_vista_Configuration.h"
#include "client_vista_AccessAccount.h"
#include "client_vista_ExitClient.h"
#include "../Client/ClientCfg.h"
#include "../Client/Cliente.h"
#include "../SocketsAndThreads/socket.h"
#include <signal.h>
#define END_APP 0
#define ACTIVE_APP 1


class MainHandler: public Gtk::Window {
public:
	MainHandler(Socket *s, std::string label, int mode, Cliente *cli) :
			access_button(label), config_button("Configuration"), exit_main_button(
					"Exit"), m_check_not_remember("Don't remember account") {

		set_title("Client Application");
		set_border_width(10);

		mode_app = mode;
		sock = s;
		client = cli;
		config_button.signal_clicked().connect(
				sigc::mem_fun(*this, &MainHandler::config));
		exit_main_button.signal_clicked().connect(
				sigc::mem_fun(*this, &MainHandler::exit_main));
		if (mode == ACTIVE_APP) {
			set_size_request(600, 500);
			if (label == "Connect") {
				image.set("./ICONO3D_IP_Conexion.png");
				end_program = false;
				unregister = true;
				connect_mode = true;
				access_button.signal_clicked().connect(
						sigc::mem_fun(*this, &MainHandler::access_account));
			} else {
				image.set("./Icono-sync.jpg");
				unregister = false;
				connect_mode = false;
				access_button.signal_clicked().connect(
						sigc::mem_fun(*this, &MainHandler::unregister_clicked));
			}

			add(box);
			box.pack_start(*Gtk::manage(&image));
			box.pack_start(access_button);
			box.pack_start(config_button);
			box.pack_start(exit_main_button);

			access_button.show();

		} else { //end app
			unregister = true;
			set_size_request(200, 300);
			add(box);
			box.pack_start(*Gtk::manage(&image));
			box.pack_start(m_check_not_remember);
			box.pack_start(config_button);
			box.pack_start(exit_main_button);
			m_check_not_remember.show();

		}
		config_button.show();
		exit_main_button.show();
		box.show();
		show_all_children();

	}

	~MainHandler() {
	}

	bool is_end_program() {
		return end_program;
	}
	bool connect() {
		std::string properties("./cfg.properties");
		ClientCfg cfg(properties); //levanta archivo de configuracion
		cfg.Initialize();
		std::string ip_server = cfg.getIp_server();

		try {
			sock->Connect(&ip_server, cfg.getPort());
			client->setSocket(sock);
		} catch (ConnectionException& e) {
			return false;
		}
		return true;
	}
protected:

	void unregister_clicked() {
		ExitClient exit_cli("¿Seguro/a que desea desconectarse?");
		Gtk::Main::run(exit_cli);
		if (exit_cli.is_exit()) {
			if (client->is_connected()) {
				Unregister *msg = new Unregister(client->getUser(),
						client->getPass());
				category.notice("Unregister sending...");
				sock->Send(msg);
				delete msg;

			}
			unregister = true;
			hide();
		}

	}

	void access_account() {
		bool connect = false;
		AccessAccount ac;
		std::string user;
		std::string pass;
		Gtk::Main::run(ac);
		bool first = true; // para el primer ciclo del connect
		if (not ac.is_cancel()) {

			if (not this->connect()) {
				Gtk::MessageDialog dialog(*this,
						"No se pudo conectar. Revise la configuracion para ver si es correcta");
				dialog.run();
			} else { //Se pudo conectar, ahora va a intentar loggearse
				connect = true;
				bool login_error = true;
				bool not_max_tries = true;
				std::string properties("./cfg.properties");
				ClientCfg cfg(properties);
				cfg.Initialize();
				do {
					if (not first) {
						Gtk::Main::run(ac);
					}
					first = false;
					if (ac.is_cancel()) {
						break;
					} else {

						user = ac.getUser();
						pass = ac.getPass();
						client->register_to_server(user, pass); //Agregar el cliente
						std::string received = sock->RecvNextMsg();
						Decoder d;
						Message *msg = d.parser(received);
						client->process_logging(d.get_id_msg(), &login_error,
								&not_max_tries);
						delete msg;
						if (login_error) {
							Gtk::MessageDialog dialog(*this, "Login error");
							dialog.run();
						} else if (not not_max_tries) {
							Gtk::MessageDialog dialog(*this, "Max tries!");
							dialog.run();
						} else { //se conecto
							std::string storage_path = cfg.getStorage_path();
							std::string indice_path = "indice.txt";
							std::string ip_server = cfg.getIp_server();
							std::string login_path;
							client->setUserPass(user, pass);
							client->initialize(sock, storage_path, indice_path,
									login_path, cfg.getPolling(), user, pass);
							Gtk::MessageDialog dialog(*this, "Conectado!");
							dialog.run();
						}
					}
				} while (login_error and not_max_tries);
				if (connect and login_error and not_max_tries) {
					sock->Shutdown(2);
				} else if (not_max_tries) { // Se pudo conectar, cerramos ventana
					//Si puso recordar, grabo en archivo de login
					if (ac.is_remember_account()) {
						std::string file_path("./login");
						Index login(&file_path);
						std::string field_user = "USER";
						std::string field_pass = "PASS";
						login.AddKey(&field_user, &user);
						login.AddKey(&field_pass, &pass);
						login.SaveToDisk();
					}
					client->start();
					category.info("Information connection:");
					category.info("Ip server: " + cfg.getIp_server());
					category.info("Port: %d", cfg.getPort());
					category.info("Storage: " + cfg.getStorage_path());
					category.info("Polling interval: %d sec", cfg.getPolling());
					end_program = false;
					hide();
				}
			}
		}
	}

	void config() {
		Configuration cfg;
		Gtk::Main::run(cfg);
	}

	void exit_main() {
		if (unregister) {
			end_program = true;
			if (mode_app == END_APP) {
				if (m_check_not_remember.get_active()) {
					std::string login_path = "login";
					std::string path = "./";
					directoryHandler dir(&path);
					if (dir.fileExists(&login_path)) {
						dir.deleteFile(&login_path);
					}

				}
				hide();

			}else{
				ExitClient exit_cli("Esta seguro/a que desea salir?");
				Gtk::Main::run(exit_cli);
				if (exit_cli.is_exit()) {
					hide();
				}
			}
		} else {
			ExitClient exit_cli("Usted esta conectado. ¿ Desea desconectarse?");
			Gtk::Main::run(exit_cli);
			if (exit_cli.is_exit()) {
				this->unregister_clicked();
			}
		}

	}

private:
	Gtk::Button access_button, config_button, exit_main_button;
	Gtk::VBox box;
	Gtk::CheckButton m_check_not_remember;
	Gtk::Image image;
	Cliente *client;
	Socket *sock;
	bool unregister; // indica si el cliente se desregistro
	bool connect_mode; // si el cliente debe conectarse, es true
	bool end_program; // si el programa debe finalizar
	int mode_app; // indica modo en que se abrio la ventana

};
#endif /* CLIENT_VISTA_MAINHANDLER_H_ */
